﻿using AIStudio.Core;
using AIStudio.Wpf.Business;
using AIStudio.Wpf.HomePage.Models;
using CommonServiceLocator;
using MahApps.Metro;
using Newtonsoft.Json;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Resources;

namespace AIStudio.Wpf.HomePage.ViewModels
{
    public class SystemSetViewModel : BindableBase
    {
        private static ILogger _logger { get => ServiceLocator.Current.GetInstance<ILogger>(); }
        private static ILocalSetting _localSetting { get => ServiceLocator.Current.GetInstance<ILocalSetting>(); }

        public SystemSetViewModel()
        {
            // create accent color menu items for the demo
            this.AccentColors = ThemeManager.Accents
                                            .Select(a => new AccentColorMenuData() { Name = a.Name, ColorBrush = a.Resources["AccentColorBrush"] as Brush })
                                            .ToList();
            this.SelectedAccentColor = this.AccentColors.FirstOrDefault(p => p.Name == _localSetting.Accent);

            // create metro theme color menu items for the demo
            this.AppThemes = ThemeManager.AppThemes
                                           .Select(a => new AppThemeMenuData() { Name = a.Name, BorderColorBrush = a.Resources["BlackColorBrush"] as Brush, ColorBrush = a.Resources["WhiteColorBrush"] as Brush })
                                           .ToList();
            this.SelectedAppTheme = this.AppThemes.FirstOrDefault(p => p.Name == _localSetting.Theme);

            this.AppNavigations = new List<AppNavigationMenuData>()
            {
                new AppNavigationMenuData() { Name = "导航栏暗色", NavigationAccent = "Dark" },
                new AppNavigationMenuData() { Name = "导航栏淡色", NavigationAccent = "Light" }
            };
            this.SelectedAppNavigation = this.AppNavigations.FirstOrDefault(p => p.NavigationAccent == _localSetting.NavigationAccent);

            this.SelectedNavigationLocation = (int)(NavigationLocation)System.Enum.Parse(typeof(NavigationLocation), _localSetting.NavigationLocation);

            this.SelectedTitleAccent = (int)(TitleAccent)System.Enum.Parse(typeof(TitleAccent), _localSetting.TitleAccent);

            this.SystemFontFamilies = new List<FontFamily>();
            foreach (FontFamily _f in Fonts.SystemFontFamilies)
            {
                LanguageSpecificStringDictionary _fontDic = _f.FamilyNames;
                if (_fontDic.ContainsKey(XmlLanguage.GetLanguage("zh-cn")))
                {
                    string _fontName = null;
                    if (_fontDic.TryGetValue(XmlLanguage.GetLanguage("zh-cn"), out _fontName))
                    {
                        this.SystemFontFamilies.Add(new FontFamily(_fontName));
                    }
                }
                //else
                //{
                //    string _fontName = null;
                //    if (_fontDic.TryGetValue(XmlLanguage.GetLanguage("en-us"), out _fontName))
                //    {
                //        SystemFontFamilies.Add(new FontFamily(_fontName));
                //    }
                //}
            }

            this._fontFamily = this.SystemFontFamilies.FirstOrDefault(p => p.Source == _localSetting.FontFamily);
            this._fontSize = _localSetting.FontSize;
            this._isChinese = _localSetting.Language == "中文";
        }

        #region 字段和属性
        public List<AccentColorMenuData> AccentColors { get; set; }

        private AccentColorMenuData _selectedAccentColor;
        public AccentColorMenuData SelectedAccentColor
        {
            get { return _selectedAccentColor; }
            set
            {
                if (_selectedAccentColor != value)
                {
                    SetProperty(ref _selectedAccentColor, value);
                }
            }
        }
        public List<AppThemeMenuData> AppThemes { get; set; }

        private AppThemeMenuData _selectedAppTheme;
        public AppThemeMenuData SelectedAppTheme
        {
            get { return _selectedAppTheme; }
            set
            {
                if (_selectedAppTheme != value)
                {
                    SetProperty(ref _selectedAppTheme, value);
                }
            }
        }
        public List<AppNavigationMenuData> AppNavigations { get; set; }

        private AppThemeMenuData _selectedAppNavigation;
        public AppThemeMenuData SelectedAppNavigation
        {
            get { return _selectedAppNavigation; }
            set
            {
                if (_selectedAppNavigation != value)
                {
                    SetProperty(ref _selectedAppNavigation, value);
                }
            }
        }

        private int _selectedNavigationLocation;
        public int SelectedNavigationLocation
        {
            get { return _selectedNavigationLocation; }
            set
            {
                if (_selectedNavigationLocation != value)
                {
                    SetProperty(ref _selectedNavigationLocation, value);
                }
            }
        }

        private int _selectedTitleAccent;
        public int SelectedTitleAccent
        {
            get { return _selectedTitleAccent; }
            set
            {
                if (_selectedTitleAccent != value)
                {
                    SetProperty(ref _selectedTitleAccent, value);
                }
            }
        }

        private int _selectedToolBarLocation;
        public int SelectedToolBarLocation
        {
            get { return _selectedToolBarLocation; }
            set
            {
                if (_selectedToolBarLocation != value)
                {
                    SetProperty(ref _selectedToolBarLocation, value);
                }
            }
        }

        private double _fontSize;
        public double FontSize
        {
            get { return _fontSize; }
            set
            {
                if (_fontSize != value)
                {
                    SetProperty(ref _fontSize, value);
                    FontSizeChange(_fontSize);
                }
            }
        }

        private bool _isChinese;

        public bool IsChinese
        {
            get { return _isChinese; }
            set
            {
                if (_isChinese != value)
                {
                    SetProperty(ref _isChinese, value);
                    LanguageChange(_isChinese);
                }
            }
        }

        public List<FontFamily> SystemFontFamilies { get; set; }

        private FontFamily _fontFamily;
        public FontFamily FontFamily
        {
            get { return _fontFamily; }
            set
            {
                if (_fontFamily != value)
                {
                    SetProperty(ref _fontFamily, value);
                    FontFamilyChange(_fontFamily);
                }
            }
        }
        #endregion

        private void LanguageChange(bool chinese)
        {
            string language = chinese ? "中文" : "英文";
            _localSetting.SetAppSetting("Language", language);
            InitLanguage();
        }

        private void FontSizeChange(double size)
        {
            _localSetting.SetAppSetting("FontSize", size);
            InitFontSize();
        }

        private void FontFamilyChange(FontFamily fontFamily)
        {
            _localSetting.SetAppSetting("FontFamily", fontFamily.Source);
            InitFontFamily();
        }

        private ICommand navigationLocationCommand;
        public ICommand NavigationLocationCommand
        {
            get
            {
                return this.navigationLocationCommand ?? (this.navigationLocationCommand = new DelegateCommand<object>(para => this.NavigationLocation(para)));
            }
        }


        private ICommand _titleAccentCommand;
        public ICommand TitleAccentCommand
        {
            get
            {
                return this._titleAccentCommand ?? (this._titleAccentCommand = new DelegateCommand<object>(para => this.TitleAccent(para)));
            }
        }

        public ICommand _toolBarLocationCommand;
        public ICommand ToolBarLocationCommand
        {
            get
            {
                return this._toolBarLocationCommand ?? (this._toolBarLocationCommand = new DelegateCommand<object>(para => this.ToolBarLocation(para)));
            }
        }

        private ICommand _changeThemeCommand;

        public ICommand ChangeThemeCommand
        {
            get { return this._changeThemeCommand ?? (_changeThemeCommand = new DelegateCommand<object>(x => this.DoChangeTheme(x))); }
        }

        private ICommand _changeAccentCommand;

        public ICommand ChangeAccentCommand
        {
            get { return this._changeAccentCommand ?? (_changeAccentCommand = new DelegateCommand<object>(x => this.DoChangeAccent(x))); }
        }

        private ICommand _changeNavigationAccentCommand;

        public ICommand ChangeNavigationAccentCommand
        {
            get { return this._changeNavigationAccentCommand ?? (_changeNavigationAccentCommand = new DelegateCommand<object>(x => this.DoChangeNavigationAccent(x))); }
        }

        private void DoChangeTheme(object para)
        {
            AppThemeMenuData data = para as AppThemeMenuData;
            if (data != null)
            {
                var theme = ThemeManager.DetectAppStyle(Application.Current);
                var appTheme = ThemeManager.GetAppTheme(data.Name);
                ThemeManager.ChangeAppStyle(Application.Current, theme.Item2, appTheme);
                DoChangeAddition(theme.Item1.Name, data.Name);
                _localSetting.SetAppSetting("Theme", data.Name);
            }
        }
        private void DoChangeAccent(object para)
        {
            AccentColorMenuData data = para as AccentColorMenuData;
            if (data != null)
            {
                var theme = ThemeManager.DetectAppStyle(Application.Current);
                var accent = ThemeManager.GetAccent(data.Name);
                ThemeManager.ChangeAppStyle(Application.Current, accent, theme.Item1);
                DoChangeAddition(theme.Item1.Name, theme.Item1.Name);
                _localSetting.SetAppSetting("Accent", data.Name);
            }
        }

        private void DoChangeAddition(string oldname, string newname)
        {
            try
            {
                string requestedStyle = "/AIStudio.Resource;component/Colors/Themes/" + oldname + "Addition.xaml";
                ResourceDictionary resourceAdditionDictionary = Application.Current.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Equals(@requestedStyle));
                Application.Current.Resources.MergedDictionaries.Remove(resourceAdditionDictionary);
                requestedStyle = "/AIStudio.Resource;component/Colors/Themes/" + newname + "Addition.xaml";
                resourceAdditionDictionary = new ResourceDictionary();
                resourceAdditionDictionary.Source = new Uri(@requestedStyle, UriKind.RelativeOrAbsolute);
                Application.Current.Resources.MergedDictionaries.Add(resourceAdditionDictionary);
                resourceAdditionDictionary.Add("TitleBackgroundBrush", resourceAdditionDictionary[_localSetting.TitleAccent == "Accent" ? "TitleBackgroundBrush2" : "TitleBackgroundBrush1"]);
                resourceAdditionDictionary.Add("TitleForegroundBrush", resourceAdditionDictionary[_localSetting.TitleAccent == "Accent" ? "TitleForegroundBrush2" : "TitleForegroundBrush1"]);
            }
            catch { }
        }

        private void DoChangeNavigationAccent(object sender)
        {
            AppNavigationMenuData navigationAccent = sender as AppNavigationMenuData;
            if (navigationAccent != null)
            {
                _localSetting.SetAppSetting("NavigationAccent", navigationAccent.NavigationAccent);
            }
        }

        private void NavigationLocation(object para)
        {
            _localSetting.SetAppSetting("NavigationLocation", ((NavigationLocation)para).ToString());
        }

        private void TitleAccent(object para)
        {
            try
            {
                _localSetting.SetAppSetting("TitleAccent", ((TitleAccent)para).ToString());
                InitThemeAddition();
            }
            catch (Exception ex)
            {
                _logger.Error(ex);
            }
        }

        private void ToolBarLocation(object para)
        {
            _localSetting.SetAppSetting("ToolBarLocation", ((ToolBarLocation)para).ToString());
        }

        public static void InitSetting()
        {
            InitFontSize();
            InitFontFamily();
            InitTheme();
            InitLanguage();
        }

        public static void InitFontSize()
        {
            #region 加载字体大小
            List<ResourceDictionary> dictionaryList = Application.Current.Resources.MergedDictionaries.ToList();

            string requestedCulture = @"/AIStudio.Wpf.HomePage;component/Themes/FontSizeDictionary.xaml";
            ResourceDictionary resourceDictionary = dictionaryList.Where(d => d.Source != null && d.Source.OriginalString.Equals(requestedCulture)).FirstOrDefault();

            resourceDictionary.Clear();
            resourceDictionary.Add("WindowTitleFontSize", _localSetting.FontSize + 2);
            resourceDictionary.Add("HeaderFontSize", _localSetting.FontSize + 2);
            resourceDictionary.Add("NormalFontSize", _localSetting.FontSize);
            resourceDictionary.Add("ContentFontSize", _localSetting.FontSize);
            resourceDictionary.Add("FlatButtonFontSize", _localSetting.FontSize);
            resourceDictionary.Add("MenuFontSize", _localSetting.FontSize);
            resourceDictionary.Add("ContextMenuFontSize", _localSetting.FontSize);
            resourceDictionary.Add("StatusBarFontSize", _localSetting.FontSize);
            resourceDictionary.Add("ToggleSwitchFontSize", _localSetting.FontSize);
            resourceDictionary.Add("ToggleSwitchHeaderFontSize", _localSetting.FontSize);
            resourceDictionary.Add("UpperCaseContentFontSize", _localSetting.FontSize);

            Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
            Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
            #endregion
        }

        public static void InitFontFamily()
        {
            #region 加载字体
            List<ResourceDictionary> dictionaryList = Application.Current.Resources.MergedDictionaries.ToList();

            FontFamily fontFamily = null;

            foreach (FontFamily fontfamily in Fonts.SystemFontFamilies)
            {
                LanguageSpecificStringDictionary fontdics = fontfamily.FamilyNames;                //判断该字体是不是中文字体       
                if (fontdics.ContainsKey(XmlLanguage.GetLanguage("zh-cn")))
                {
                    string fontfamilyname = null;
                    if (fontdics.TryGetValue(XmlLanguage.GetLanguage("zh-cn"), out fontfamilyname))
                    {
                        if (fontfamilyname.Contains(_localSetting.FontFamily))
                        { fontFamily = fontfamily; break; }
                    }
                }                //英文字体     
                else
                {
                    string fontfamilyname = null;
                    if (fontdics.TryGetValue(XmlLanguage.GetLanguage("en-us"), out fontfamilyname))
                    {
                        if (fontfamilyname.Contains(_localSetting.FontFamily))
                        { fontFamily = fontfamily; break; }
                    }
                }
            }

            if (fontFamily == null)
                return;

            string requestedCulture = @"/AIStudio.Wpf.HomePage;component/Themes/FontFamilyDictionary.xaml";
            ResourceDictionary resourceDictionary = dictionaryList.Where(d => d.Source != null && d.Source.OriginalString.Equals(requestedCulture)).FirstOrDefault();

            resourceDictionary.Clear();
            resourceDictionary.Add("DefaultFont", fontFamily);
            resourceDictionary.Add("HeaderFontFamily", fontFamily);
            resourceDictionary.Add("ContentFontFamily", fontFamily);
            resourceDictionary.Add("ToggleSwitchFontFamily", fontFamily);
            resourceDictionary.Add("ToggleSwitchHeaderFontFamily", fontFamily);
            resourceDictionary.Add("ToggleSwitchFontFamily.Win10", fontFamily);
            resourceDictionary.Add("ToggleSwitchHeaderFontFamily.Win10", fontFamily);

            Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
            Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
            #endregion
        }

        private static void InitThemeAddition()
        {
            var requestedAdditionStyle = $"/AIStudio.Resource;component/Colors/Themes/{_localSetting.Theme}Addition.xaml";
            var resourceAdditionDictionary = new ResourceDictionary();
            resourceAdditionDictionary.Source = new Uri(@requestedAdditionStyle, UriKind.RelativeOrAbsolute);
            Application.Current.Resources.MergedDictionaries.Add(resourceAdditionDictionary);
            resourceAdditionDictionary.Add("TitleBackgroundBrush", resourceAdditionDictionary[_localSetting.TitleAccent == "Accent" ? "TitleBackgroundBrush2" : "TitleBackgroundBrush1"]);
            resourceAdditionDictionary.Add("TitleForegroundBrush", resourceAdditionDictionary[_localSetting.TitleAccent == "Accent" ? "TitleForegroundBrush2" : "TitleForegroundBrush1"]);
        }

        public static void InitTheme()
        {
            #region 加载主题
            try
            {
                List<ResourceDictionary> dictionaryList = Application.Current.Resources.MergedDictionaries.ToList();

                //ThemeManager.AddAppTheme("BaseGray", new Uri("pack://application:,,,/AIStudio.Resource;component/Colors/Themes/BaseGray.xaml"));
                //ThemeManager.AddAccent("BlueGray", new Uri("pack://application:,,,/AIStudio.Resource;component/Colors/Accents/BlueGray.xaml"));
                //ThemeManager.AddAccent("Primary", new Uri("pack://application:,,,/AIStudio.Resource;component/Colors/Accents/Primary.xaml"));

                var resourceStream = Application.GetResourceStream(new Uri("pack://application:,,,/AIStudio.Resource;component/Colors/Color.json"));
                if (resourceStream != null)
                {
                    using (var reader = new StreamReader(resourceStream.Stream))
                    {
                        var jsonStr = reader.ReadToEnd();
                        var jsonObj = JsonConvert.DeserializeObject<dynamic>(jsonStr);
                        foreach (var item in (dynamic)jsonObj.Themes)
                        {
                            ThemeManager.AddAppTheme((string)item[0], new Uri((string)item[1]));
                        }

                        foreach (var item in (dynamic)jsonObj.Accents)
                        {
                            ThemeManager.AddAccent((string)item[0], new Uri((string)item[1]));
                        }
                    }
                }

                //添加额外的信息
                InitThemeAddition();

                var theme = ThemeManager.DetectAppStyle(Application.Current);
                if (theme.Item1.Name == _localSetting.Theme && theme.Item2.Name == _localSetting.Accent)
                {
                    return;
                }
                var accent = ThemeManager.GetAccent(_localSetting.Accent);
                var appTheme = ThemeManager.GetAppTheme(_localSetting.Theme);
                ThemeManager.ChangeAppStyle(Application.Current, accent, appTheme);

                //添加额外的信息
                InitThemeAddition();
            }
            catch (Exception ex)
            {
                _logger.Error(ex);
            }
            //string requestedStyle = "/AIStudio.Resource;component/Colors/Additions/" + theme.Item2.Name + "Addition.xaml";
            //ResourceDictionary resourceDictionary = Application.Current.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains("/AIC.Resources;component/Styles/") && d.Source.OriginalString.Contains("Addition.xaml"));
            //Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
            //requestedStyle = "/AIStudio.Resource;component/Colors/Additions/" + accent.Name + "Addition.xaml";
            //resourceDictionary = new ResourceDictionary();
            //resourceDictionary.Source = new Uri(@requestedStyle, UriKind.RelativeOrAbsolute);
            //Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);

            string requestedStyle = "/AIStudio.Resource;component/Brushs/Brushes.xaml";
            ResourceDictionary resourceDictionary = Application.Current.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains("/AIC.Resources;component/Styles/") && d.Source.OriginalString.Contains("Addition.xaml"));
            Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
            requestedStyle = "/AIStudio.Resource;component/Brushs/Brushes.xaml";
            resourceDictionary = new ResourceDictionary();
            resourceDictionary.Source = new Uri(@requestedStyle, UriKind.RelativeOrAbsolute);
            Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
            #endregion
        }

        public static void InitLanguage()
        {
            List<ResourceDictionary> dictionaryList = Application.Current.Resources.MergedDictionaries.ToList();
            string chineseCulture = @"/AIStudio.Resource;component/Themes/zh-cn.xaml";
            string englishCulture = @"/AIStudio.Resource;component/Themes/en-us.xaml";
            string requestedCulture = _localSetting.Language == "中文" ? chineseCulture : englishCulture;
            ResourceDictionary resourceDictionary = dictionaryList.Where(d => d.Source != null && d.Source.OriginalString.Equals(requestedCulture)).FirstOrDefault();
            Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
            Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
        }
    }
}
